Skip to content

[Streams] Fix VoiceOver announcement of "Add attachments" flyout (#224746)#267805

Merged
rStelmach merged 5 commits into
elastic:mainfrom
rStelmach:224746-observabilitystreams-add-a-dashboard-flyout-announced-incorrectly-on-individual-streams-page
May 6, 2026
Merged

[Streams] Fix VoiceOver announcement of "Add attachments" flyout (#224746)#267805
rStelmach merged 5 commits into
elastic:mainfrom
rStelmach:224746-observabilitystreams-add-a-dashboard-flyout-announced-incorrectly-on-individual-streams-page

Conversation

@rStelmach
Copy link
Copy Markdown
Contributor

@rStelmach rStelmach commented May 5, 2026

closes #224746

Summary

When a screen reader user opened the Add attachments flyout on the individual stream page (Attachments tab → "Add attachment" button), VoiceOver announced the dialog as just "…modal dialog…" with no accessible name — leaving non-sighted users with no idea which dialog they had just entered.

The flyout already had aria-labelledby pointing to the <h2> header, but in practice VoiceOver + WebKit silently failed to compute the accessible name from that IDREF (the id contained colons from React's useId()), and there was no fallback. The result was an empty accessible name, which violates WCAG 2.1 SC 1.3.1 — Info and Relationships (Level A).

Fix

Replaced aria-labelledby (which silently resolved to an empty accessible name in VoiceOver) with a direct aria-label on EuiFlyout, sourced from the same i18n string as the visible <h2> heading.

VoiceOver now announces:

"Add attachments, dialog, with 6 items. You are in a modal dialog. Press Escape or tap/click outside the dialog on the shadowed overlay to close…"

image

The visible <h2> heading is preserved for sighted users; the i18n constant is shared between the visible text and the accessible name so they cannot drift.

@rStelmach rStelmach added release_note:skip Skip the PR/issue when compiling release notes backport:skip This PR does not require backporting Team:obs-onboarding Observability Onboarding Team Feature:Streams This is the label for the Streams Project labels May 5, 2026
@rStelmach rStelmach marked this pull request as ready for review May 5, 2026 17:08
@rStelmach rStelmach requested review from a team as code owners May 5, 2026 17:08
@infra-vault-gh-plugin-prod
Copy link
Copy Markdown

Pinging @elastic/obs-onboarding-team (Team:obs-onboarding)

@macroscopeapp
Copy link
Copy Markdown
Contributor

macroscopeapp Bot commented May 5, 2026

Approvability

Verdict: Needs human review

Simple accessibility fix replacing aria-labelledby with aria-label for VoiceOver support. However, the author is not a designated owner of the modified file, which is owned by @elastic/obs-onboarding-team and @elastic/obs-sig-events-team.

You can customize Macroscope's approvability policy. Learn more.

Copy link
Copy Markdown
Contributor

@cesco-f cesco-f left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM


const flyoutTitleId = useGeneratedHtmlId({
prefix: 'addAttachmentFlyoutTitle',
const flyoutTitleLabel = i18n.translate('xpack.streams.addAttachmentFlyout.flyoutHeaderLabel', {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: now that the hook is gone, this variable can be moved to module scope.

@rStelmach rStelmach enabled auto-merge (squash) May 6, 2026 10:44
@kibanamachine
Copy link
Copy Markdown
Contributor

💛 Build succeeded, but was flaky

Failed CI Steps

Test Failures

  • [job] [logs] FTR Configs #211 / Dashboard save a search sessions TSVB & Timelion Restore session with TSVB & Timelion

Metrics [docs]

Async chunks

Total size of all lazy-loaded chunks that will be downloaded as the user navigates the app

id before after diff
streamsApp 2.0MB 2.0MB -58.0B

History

@rStelmach rStelmach merged commit f12a893 into elastic:main May 6, 2026
31 checks passed
ersin-erdal pushed a commit to ersin-erdal/kibana that referenced this pull request May 6, 2026
…stic#224746) (elastic#267805)

closes elastic#224746

## Summary


When a screen reader user opened the **Add attachments** flyout on the
individual stream page (Attachments tab → "Add attachment" button),
VoiceOver announced the dialog as just *"…modal dialog…"* with no
accessible name — leaving non-sighted users with no idea which dialog
they had just entered.

The flyout already had `aria-labelledby` pointing to the `<h2>` header,
but in practice VoiceOver + WebKit silently failed to compute the
accessible name from that IDREF (the id contained colons from React's
`useId()`), and there was no fallback. The result was an empty
accessible name, which violates **WCAG 2.1 SC 1.3.1 — Info and
Relationships (Level A)**.

### Fix

Replaced `aria-labelledby` (which silently resolved to an empty
accessible name in VoiceOver) with a direct `aria-label` on `EuiFlyout`,
sourced from the same i18n string as the visible `<h2>` heading.

VoiceOver now announces:

> **"Add attachments, dialog, with 6 items. You are in a modal dialog.
Press Escape or tap/click outside the dialog on the shadowed overlay to
close…"**

<img width="2359" height="1266" alt="image"
src="https://github.com/user-attachments/assets/10ae6d6d-0f13-4d64-81c7-ccda1720bdf7"
/>

The visible `<h2>` heading is preserved for sighted users; the i18n
constant is shared between the visible text and the accessible name so
they cannot drift.

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport:skip This PR does not require backporting Feature:Streams This is the label for the Streams Project release_note:skip Skip the PR/issue when compiling release notes Team:obs-onboarding Observability Onboarding Team v9.5.0

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Observability:Streams] Add a dashboard flyout announced incorrectly on individual streams page

3 participants